package com.example.moudlelibrary.tools;

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.command.*;
import com.github.dockerjava.api.exception.DockerException;
import com.github.dockerjava.api.model.*;
import com.github.dockerjava.core.command.ExecStartResultCallback;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.ByteArrayOutputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author TRY
 * @Date 2023/4/6 14:04
 * @Version 1.0
 */
@Service
public class DockerService {

    @Autowired
    DockerClient dockerClient;
    int startPort = 50000;
    @Autowired
    WebSocketService webSocketService;

    String exeId;


    /**
     * @param imageName     镜像名称
     * @param containerName 容器名称
     * @param volumePath    实际映射空间地址
     * @param workDir       工作空间地址
     * @return: java.lang.String
     * @Description: 创建docker容器
     * @Author: HeYuanqing
     * @Date: 2023/9/22 10:58
     */
    public String createContainer(String imageName, String containerName, String volumePath, String workDir) {
        PortBinding portBinding = PortBinding.parse(startPort + ":" + startPort);
        Volume workVolume = new Volume("/" + workDir);
        volumePath.replace("\\", "/");
        Bind workBind = new Bind(volumePath, workVolume);
        List<Bind> bindList = new ArrayList<Bind>();
        bindList.add(workBind);
        List<Volume> volumeList = new ArrayList<Volume>();
        volumeList.add(workVolume);
        // 创建容器
        CreateContainerResponse container = dockerClient.createContainerCmd(imageName)
                .withName(containerName)
                .withStdinOpen(true)
                .withTty(true)
                .withWorkingDir("/" + workDir)
                .withExposedPorts(ExposedPort.tcp(startPort))
                .withPortBindings(portBinding)
                .withBinds(bindList)
                .withVolumes(volumeList)
                .exec();
        String containerId = container.getId();
        startPort++;
        return containerId;
    }

    /**
     * @param containerId 容器ID
     * @return: boolean
     * @Description: 检查容器状态, 启动返回true，否则返回false
     * @Author: HeYuanqing
     * @Date: 2023/9/22 11:07
     */
    public boolean checkState(String containerId) {
        boolean running = false;
        List<Container> containers = dockerClient.listContainersCmd().exec();
        System.out.println(containers);
        for (Container container : containers) {
            if (container.getId().equals(containerId)) {
                running = true;
            }
        }
        return running;
    }

    /**
     * @param containerId 容器ID
     * @return: void
     * @Description: 启动容器
     * @Author: HeYuanqing
     * @Date: 2023/9/22 11:08
     */
    public void startContainer(String containerId) throws DockerException, InterruptedException {
        dockerClient.startContainerCmd(containerId).exec();
    }

    public void writeFileToContainer(String containerId, String filePath, String fileContent) throws InterruptedException {
        // 将文件内容转换为字节数组
        byte[] contentBytes = fileContent.getBytes(StandardCharsets.UTF_8);

        // 使用Docker客户端的execCreateCmd方法创建一个命令
        String execCmd = "echo -n \"" + new String(contentBytes, StandardCharsets.UTF_8) + "\" > " + filePath;
        runCMD(containerId, execCmd);

    }

    public ResultMessage runCMD(String containerId, String command) throws InterruptedException {
        String[] cmd = {"/bin/bash", "-c", command};
        ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(containerId)
                .withAttachStdout(true)
                .withAttachStderr(true)
                .withTty(true)
                .withAttachStdin(true)
                .withCmd(cmd)
                .exec();

        ResultMessage resultMessages = new ResultMessage("", new ArrayList<>());
        ExecResultCallback callback = new ExecResultCallback(resultMessages);

        dockerClient.execStartCmd(execCreateCmdResponse.getId())
                .exec(callback)
                .awaitCompletion();

        return callback.resultMessage;
    }

    public void rundemotest(String containerId, String command) throws InterruptedException {
        Map<String, String> map = new HashMap<String, String>();
        String[] cmd = {"/bin/bash", "-c", command};
        ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(containerId)
                .withAttachStdout(true)
                .withAttachStderr(true)
                .withTty(true)
                .withAttachStdin(true)
                .withCmd(cmd)
                .exec();
        ResultMessage resultMessages = new ResultMessage("", new ArrayList<>());
        ExecResultCallback callback = new ExecResultCallback(resultMessages);
        exeId = execCreateCmdResponse.getId();

        dockerClient.execStartCmd(exeId)
                .exec(callback)
                .awaitCompletion();

        System.out.println("debug");
    }

    public void runCMD(String containerId, String projectId, String command) throws InterruptedException {

        String[] cmd = {"/bin/bash", "-c", command};
        ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(containerId)
                .withAttachStdout(true)
                .withAttachStderr(true)
                .withTty(true)
                .withAttachStdin(true)
                .withCmd(cmd)
                .exec();

        MyExecStartResultCallback callback = new MyExecStartResultCallback(projectId, webSocketService);
        dockerClient.execStartCmd(execCreateCmdResponse.getId()).exec(callback).awaitCompletion();
    }

    //下载依赖文件
    public void downloadDep(String containerId, String projectId) throws InterruptedException {
        String[] cmd = {"/bin/bash", "-c", "pip install -r requirements.txt"};
        ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(containerId)
                .withAttachStdout(true)
                .withAttachStderr(true)
                .withTty(true)
                .withAttachStdin(true)
                .withCmd(cmd)
                .exec();
        MyExecStartResultCallback callback = new MyExecStartResultCallback(projectId, webSocketService);
        dockerClient.execStartCmd(execCreateCmdResponse.getId()).exec(callback).awaitCompletion();
    }

    //下载依赖文件
    public void downloadDep(String containerId) throws InterruptedException {
        String[] cmd = {"/bin/bash", "-c", "pip install -r requirements.txt"};
        ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(containerId)
                .withAttachStdout(true)
                .withAttachStderr(true)
                .withTty(true)
                .withAttachStdin(true)
                .withCmd(cmd)
                .exec();
        dockerClient.execStartCmd(execCreateCmdResponse.getId()).exec((new ExecStartResultCallback(System.out, System.err))).awaitCompletion();
    }

    //运行
    public void runScript(String containerId, String projectId) throws InterruptedException {
        Map<String, String> map = new HashMap<String, String>();
        String[] cmd = {"/bin/bash", "-c", "python main.py"};
        ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(containerId)
                .withAttachStdout(true)
                .withAttachStderr(true)
                .withTty(true)
                .withAttachStdin(true)
                .withCmd(cmd)
                .exec();
        MyExecStartResultCallback callback = new MyExecStartResultCallback(projectId, webSocketService);
        exeId = execCreateCmdResponse.getId();
        dockerClient.execStartCmd(exeId).exec(callback).awaitCompletion();
    }

    //运行
    public void runScript(String containerId, String userId, String pyFileName, List<executeParam> executeParams, String workDir) throws InterruptedException {
        Map<String, String> map = new HashMap<String, String>();
        String executeOrder = "python " + pyFileName;
        for (int i = 0; i < executeParams.size(); i++) {
            executeParam executeParam = executeParams.get(i);
            String pre = executeParam.getPre();
            String value = executeParam.getValue();
            executeOrder = executeOrder + " " + pre + " " + value;
        }
        String[] cmd = {"/bin/bash", "-c", executeOrder};
        ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(containerId)
                .withAttachStdout(true)
                .withAttachStderr(true)
                .withTty(true)
                .withAttachStdin(true)
                .withCmd(cmd)
                .exec();
//        MyExecStartResultCallback callback=new MyExecStartResultCallback(userId,webSocketService);
        exeId = execCreateCmdResponse.getId();
        dockerClient.execStartCmd(exeId).exec((new ExecStartResultCallback(System.out, System.err))).awaitCompletion();
    }

    public void runScript(String containerId) throws InterruptedException {

        Map<String, String> map = new HashMap<String, String>();
        String[] cmd = {"/bin/bash", "-c", "python main.py"};
        ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(containerId)
                .withAttachStdout(true)
                .withAttachStderr(true)
                .withTty(true)
                .withAttachStdin(true)
                .withCmd(cmd)
                .exec();
//        MyExecStartResultCallback callback=new MyExecStartResultCallback(userId,webSocketService);
        exeId = execCreateCmdResponse.getId();
        dockerClient.execStartCmd(exeId).exec((new ExecStartResultCallback(System.out, System.err))).awaitCompletion();
    }


    // 停止容器
    public void closeContainer(String containerId) throws DockerException, InterruptedException {
        dockerClient.stopContainerCmd(containerId).exec();
    }

    // 删除容器
    public void removeContainer(String containerId) throws DockerException, InterruptedException {
        RemoveContainerCmd removeContainerCmd = dockerClient.removeContainerCmd(containerId);
        removeContainerCmd.withForce(true).exec();
    }


    public void stopScript(String containerId, String projectId) throws InterruptedException {
        String[] cmd = {"/bin/bash", "-c", "kill -INT `pidof python`"};

        // 执行命令
        ExecCreateCmdResponse execCreateCmdResponse = dockerClient.execCreateCmd(containerId)
                .withAttachStdout(true)
                .withAttachStderr(true)
                .withTty(true)
                .withAttachStdin(true)
                .withCmd(cmd)
                .exec();
        MyExecStartResultCallback callback = new MyExecStartResultCallback(projectId, webSocketService);
        dockerClient.execStartCmd(execCreateCmdResponse.getId()).exec(callback).awaitCompletion();
    }
}
